from django.contrib import admin
from django.core.exceptions import ObjectDoesNotExist
from simple_history.admin import SimpleHistoryAdmin

from sysreptor.pentests.models import (
    ArchivedProject,
    ArchivedProjectKeyPart,
    ArchivedProjectPublicKeyEncryptedKeyPart,
    CollabClientInfo,
    CollabEvent,
    Comment,
    CommentAnswer,
    FindingTemplate,
    FindingTemplateTranslation,
    PentestFinding,
    PentestProject,
    ProjectMemberInfo,
    ProjectMemberRole,
    ProjectNotebookExcalidrawFile,
    ProjectNotebookPage,
    ProjectType,
    ReportSection,
    ShareInfo,
    UploadedAsset,
    UploadedImage,
    UploadedProjectFile,
    UploadedTemplateImage,
    UploadedUserNotebookFile,
    UploadedUserNotebookImage,
    UserNotebookExcalidrawFile,
    UserNotebookPage,
    UserPublicKey,
)
from sysreptor.utils.admin import BaseAdmin, admin_change_url, admin_changelist_url


@admin.register(ProjectType)
class ProjectTypeAdmin(SimpleHistoryAdmin, BaseAdmin):
    list_display = ['id', 'name', 'created', 'status', 'tags']
    readonly_fields = ('default_notes',)

    def link_projects(self, obj):
        return admin_changelist_url('Projects using this ProjectType', 'pentests', 'pentestproject', {'project_type_id': obj.id})

    def link_uploaded_assets(self, obj):
        return admin_change_url('Uploaded assets', 'pentests', 'uploadedasset', {'projecttype_id': obj.id})


@admin.register(ProjectMemberRole)
class ProjectMemberRoleAdmin(SimpleHistoryAdmin, BaseAdmin):
    list_display = ['role', 'default']


class ProjectMemberInfoInlineAdmin(admin.StackedInline):
    model = ProjectMemberInfo


@admin.register(ProjectMemberInfo)
class ProjectMemberInfoAdmin(SimpleHistoryAdmin, BaseAdmin):
    list_display = ['user__username', 'project__name', 'roles']
    search_fields = ['user__username', 'user__email', 'project__name']
    list_select_related = ['user', 'project']


@admin.register(PentestProject)
class PentestProjectAdmin(SimpleHistoryAdmin, BaseAdmin):
    list_display = ['id', 'name', 'created', 'readonly', 'tags']
    search_fields = ['name', 'tags', 'members__user__username']
    inlines = [ProjectMemberInfoInlineAdmin]
    readonly_fields = ('imported_members',)

    def link_findings(self, obj):
        return admin_changelist_url('Findings of this project', 'pentests', 'pentestfinding', {'project_id': obj.id})

    def link_sections(self, obj):
        return admin_changelist_url('Sections of this project', 'pentests', 'reportsection', {'project_id': obj.id})

    def link_project_type(self, obj):
        return admin_change_url(obj.project_type.name, 'pentests', 'projecttype', obj.project_type.id)

    def link_uploaded_images(self, obj):
        return admin_changelist_url('Uploaded images', 'pentests', 'uploadedimage', {'linked_object_id': obj.id})

    def link_notes(self, obj):
        return admin_changelist_url('Notebook pages', 'pentests', 'projectnotebookpage', {'project_id': obj.id})

    def link_uploaded_files(self, obj):
        return admin_changelist_url('Uploaded files', 'pentests', 'uploadedprojectfile', {'linked_object_id': obj.id})

    def link_shared_notes(self, obj):
        return admin_changelist_url('Shared notes', 'pentests', 'shareinfo', {'note__project_id': obj.id})


@admin.register(PentestFinding)
class PentestFindingAdmin(SimpleHistoryAdmin, BaseAdmin):
    list_display = ['id', 'title', 'project', 'created', 'status']
    readonly_fields = ['project']


@admin.register(ReportSection)
class ReportSectionAdmin(SimpleHistoryAdmin, BaseAdmin):
    list_display = ['id', 'section_label', 'project', 'status']
    list_select_related = ['project__project_type']
    readonly_fields = ['project']


@admin.register(Comment)
class CommentAdmin(BaseAdmin):
    list_display = ['id', 'text', 'path', 'status', 'created', 'user']
    readonly_fields = ['finding', 'section', 'user']

    def link_answers(self, obj):
        return admin_changelist_url('Answers', 'pentests', 'commentanswer', {'comment_id': obj.id})

    def link_project(self, obj):
        return admin_change_url(obj.project.name, 'pentests', 'pentestproject', obj.project.id)


@admin.register(CommentAnswer)
class CommentAnswerAdmin(BaseAdmin):
    list_display = ['id', 'text', 'created', 'user']
    readonly_fields = ['comment']


@admin.register(ProjectNotebookPage)
class ProjectNotebookPageAdmin(SimpleHistoryAdmin, BaseAdmin):
    list_display = ['id', 'title', 'project', 'created', 'checked']
    readonly_fields = ['project']

    def link_excalidraw_data(self, obj):
        try:
            return admin_change_url('Excalidraw Data', 'pentests', 'projectnotebookexcalidrawfile', obj.excalidraw_file.id)
        except ObjectDoesNotExist:
            return None


@admin.register(UserNotebookPage)
class UserNotebookPageAdmin(BaseAdmin):
    list_display = ['id', 'title', 'user', 'created', 'checked']
    readonly_fields = ['user']

    def link_excalidraw_data(self, obj):
        try:
            return admin_change_url('Excalidraw Data', 'pentests', 'usernotebookexcalidrawfile', obj.excalidraw_file.id)
        except ObjectDoesNotExist:
            return None


@admin.register(FindingTemplate)
class FindingTemplateAdmin(SimpleHistoryAdmin, BaseAdmin):
    list_display = ['id', 'main_translation', 'created', 'tags']
    list_select_related = ['main_translation']
    readonly_fields = ['main_translation']

    def link_translations(self, obj):
        return admin_changelist_url('Translations', 'pentests', 'findingtemplatetranslation', {'template_id': obj.id})

    def link_images(self, obj):
        return admin_changelist_url('Images', 'pentests', 'uploadedtemplateimage', {'template_id': obj.id})


@admin.register(FindingTemplateTranslation)
class FindingTemplateTranslationAdmin(SimpleHistoryAdmin, BaseAdmin):
    list_display = ['id', 'title', 'language', 'created', 'status']
    readonly_fields = ['template']


class FileAdminBase(SimpleHistoryAdmin, BaseAdmin):
    list_display = ['id', 'created', 'linked_object', 'name']
    readonly_fields = ['linked_object']


@admin.register(UploadedImage)
class UploadedImageAdmin(FileAdminBase):
    pass


@admin.register(UploadedAsset)
class UploadedAssetAdmin(FileAdminBase):
    pass


@admin.register(UploadedProjectFile)
class UploadedProjectFileAdmin(FileAdminBase):
    pass


@admin.register(UploadedUserNotebookImage)
class UploadedUserNotebookImageAdmin(FileAdminBase):
    pass


@admin.register(UploadedTemplateImage)
class UploadedTemplateImageAdmin(FileAdminBase):
    pass


@admin.register(UploadedUserNotebookFile)
class UploadedUserNotebookFileAdmin(FileAdminBase):
    pass


@admin.register(ProjectNotebookExcalidrawFile)
class ProjectNotebookExcalidrawFileAdmin(FileAdminBase):
    list_display = ['id', 'created', 'linked_object']


@admin.register(UserNotebookExcalidrawFile)
class UserNotebookExcalidrawFileAdmin(FileAdminBase):
    list_display = ['id', 'created', 'linked_object']


@admin.register(UserPublicKey)
class UserPublicKeyAdmin(BaseAdmin):
    list_display = ['id', 'user', 'name', 'created', 'enabled']
    readonly_fields = ['user']

    def link_encrypted_key_parts(self, obj):
        return admin_changelist_url('ArchivedProjectPublicKeyEncryptedKeyPart encrypted with this public key', 'pentests', 'archivedprojectpublickeyencryptedkeypart', {'public_key_id': obj.id})


@admin.register(ArchivedProject)
class ArchivedProjectAdmin(BaseAdmin):
    list_display = ['id', 'name', 'created', 'tags']

    def link_key_parts(self, obj):
        return admin_changelist_url('key parts', 'pentests', 'archivedprojectkeypart', {'archived_project_id': obj.id})


@admin.register(ArchivedProjectKeyPart)
class ArchivedProjectKeyPartAdmin(BaseAdmin):
    list_display = ['id', 'archived_project', 'user', 'is_decrypted', 'decrypted_at']
    list_select_related = ['archived_project', 'user']
    readonly_fields = ['archived_project', 'user']

    def link_encrypted_key_parts(self, obj):
        return admin_changelist_url('Encrypted key part data', 'pentests', 'archivedprojectpublickeyencryptedkeypart', {'key_part_id': obj.id})


@admin.register(ArchivedProjectPublicKeyEncryptedKeyPart)
class ArchivedProjectPublicKeyEncryptedKeyPartAdmin(BaseAdmin):
    readonly_fields = ['key_part', 'public_key', 'encrypted_data']


@admin.register(CollabEvent)
class CollabEventAdmin(BaseAdmin):
    list_display = ['id', 'created', 'related_id', 'type']


@admin.register(CollabClientInfo)
class CollabClientInfoAdmin(BaseAdmin):
    list_display = ['id', 'created', 'user', 'client_id', 'path']
    readonly_fields = ['user']


@admin.register(ShareInfo)
class ShareInfoAdmin(BaseAdmin):
    list_display = ['id', 'created', 'project_name', 'note_title']
    readonly_fields = ['note', 'shared_by']
    list_select_related = ['note__project']

    def project_name(self, obj):
        return obj.note.project.name

    def note_title(self, obj):
        return obj.note.title

    def link_project(self, obj):
        return admin_change_url(obj.note.project.name, 'pentests', 'pentestproject', obj.note.project.id)

